package blue.http.internal.core.parser;

import blue.base.core.reflect.JavaBean;
import blue.http.core.annotation.Filter;
import blue.http.core.annotation.Http;
import blue.http.core.annotation.WebSocket;
import blue.http.internal.core.parser.parameter.ParamParserFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.annotation.Annotation;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @author Jin Zheng
 * @since 1.0 2021-08-05
 */
public class ParserFactory {
	private static Logger logger = LoggerFactory.getLogger(ParserFactory.class);
	private static Set<Class<? extends Annotation>> annotationSet = Set.of(Http.class, Filter.class, WebSocket.class);

	private final Map<Class<? extends Annotation>, Parser> parserMap = new HashMap<>();
	private final ParamParserFactory paramParserFactory = new ParamParserFactory();
	private final HttpConfigCache httpConfigCache = new HttpConfigCache();
	private final FilterConfigCache filterConfigCache = new FilterConfigCache();
	private final WebSocketConfigCache webSocketConfigCache = new WebSocketConfigCache();

	public ParserFactory() {
		parserMap.put(Http.class, new HttpParser(paramParserFactory, httpConfigCache));
		parserMap.put(Filter.class, new FilterParser(filterConfigCache));
		parserMap.put(WebSocket.class, new WebSocketParser(paramParserFactory, webSocketConfigCache));
	}

	public void parse(Object target, Class<?> clazz) {
		JavaBean javaBean = JavaBean.parse(target, clazz);
		var annotationList = javaBean.getAnnotations();
		for (var annotation : annotationList) {
			if (!annotationSet.contains(annotation.annotationType()))
				continue;

			Parser parser = parserMap.get(annotation.annotationType());
			if (parser != null) {
				logger.debug("Found {} Handler: {}", annotation.annotationType().getSimpleName(), parser);
				parser.parse(javaBean);
				break;
			}
		}
	}

	public HttpConfigCache getHttpConfigCache() {
		return httpConfigCache;
	}

	public FilterConfigCache getFilterConfigCache() {
		return filterConfigCache;
	}

	public WebSocketConfigCache getWebSocketConfigCache() {
		return webSocketConfigCache;
	}

}
